using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;

namespace Agro2D
{
    public class AnimationFactory
    {
        public AnimationFactory()
        {
            this.animTypes = new Dictionary<string, IAnimation>();

            // Add built-in types
            this.animTypes.Add("ActionAnimation", new ActionAnimation());
            this.animTypes.Add("BlinkAnimation", new BlinkAnimation());
            this.animTypes.Add("CompositeAnimation", new CompositeAnimation());
            this.animTypes.Add("DelayAnimation", new DelayAnimation());
            this.animTypes.Add("FrameAnimation", new FrameAnimation());
            this.animTypes.Add("LoopAnimation", new LoopAnimation());
            this.animTypes.Add("MoveAnimation", new MoveAnimation());
            this.animTypes.Add("RotateAnimation", new RotateAnimation());
            this.animTypes.Add("SequenceAnimation", new SequenceAnimation());
        }
        #region Public Interface
        /// <summary>
        /// Use this method to instantiate a Template at run-time.
        /// 'Overload' any of its data that you need modified.
        /// This functionality is used internally by Level to overload types.
        /// </summary>
        /// <param name="type">The name of the type to instantiate</param>
        /// <returns>A IAnimation of the the C# type and custom IAnimation type specified in the type file</returns>
        public IAnimation CreateAnimation(string type)
        {
            Debug.Assert(type.Length > 0);
            Debug.Assert(animTypes.ContainsKey(type), "IAnimation type: \"" + type + "\" not registered with AnimationFactory");

            if(animTypes.ContainsKey(type))
            {
                return (IAnimation)animTypes[type].Clone();
            }
            else
            {
                Log.Instance.LogMessage("SpriteManager.CreateSprite: type \"" + type + "\" has not been loaded");
                return null;
            }
        }

        

        /// <summary>
        /// Register a IAnimation with the Factory so it can be created through CreateSprite later.
        /// This will save you duplicating loading code.
        /// </summary>
        /// <param name="type">The name to give the type you are creating</param>
        /// <param name="obj">The actual IAnimation with which to clone later through CreateSprite</param>
        public void AddAnimationType(string type, IAnimation anim)
        {
            Debug.Assert(!animTypes.ContainsKey(type));

            if(!animTypes.ContainsKey(type))
                animTypes.Add(type, anim);
            else
            {
                Log.Instance.LogMessage("AnimationFactory.AddSprite: type \"" + type
                    + "\" has already been added to AnimationFactory");
            }
        }

        /// <summary>
        /// Remove a IAnimation from the factory; it won't be able to be instantiated later.
        /// </summary>
        /// <param name="IAnimation">The type of IAnimation with which to remove</param>
        public void RemoveAnimationType(IAnimation anim)
        {
            Debug.Assert(animTypes.ContainsValue(anim));

            if(animTypes.ContainsValue(anim))
            {
                foreach(KeyValuePair<string, IAnimation> localanim in animTypes) {
                    if(anim == localanim.Value)
                        animTypes.Remove(localanim.Key);
                }

            }
            else
            {
                Log.Instance.LogMessage("AnimationFactory.RemoveSprite: type \"" + anim.ToString()
                    + "\" does not exist in AnimationFactory");
            }

        }
        /// <summary>
        /// Remove a IAnimation from the Factory; it won't be able to be instantiated later.
        /// </summary>
        /// <param name="IAnimation">The type of IAnimation with which to remove</param>
        public void RemoveAnimationType(string type)
        {
            Debug.Assert(animTypes.ContainsKey(type));

            if(animTypes.ContainsKey(type))
                animTypes.Remove(type);
            else
            {
                Log.Instance.LogMessage("AnimationFactory.RemoveSprite: type \"" + type + "\" does not exist in AnimationFactory");
            }
        }

        /// <summary>
        /// Clear all IAnimations from the Factory.
        /// </summary>
        public void Clear()
        {
            animTypes.Clear();
        }
        #endregion

        public static AnimationFactory Instance
        {
            get { return instance; }
        }

        // Prototypes.
        private static readonly AnimationFactory instance = new AnimationFactory();
        protected Dictionary<string, IAnimation> animTypes;
    }
}